/**
 * @file        motor_drive.c
 * @brief       驱动电机所需的片上ADC、PWM驱动
 * @version     V1.2
 * @author      Jsir2022 (jsir2022@outlook.com)
 * @date        2024-02-28 22:46:29
 * LastEditors  Jsir2022
 * LastEditTime 2024-03-02 15:43:35
 * history		版本	日期		作者		说明
 * 				V1.0	2024-2-28	Jsir2022	实现了六步开环强拖
 *              V1.1	2024-3-1	Jsir2022	更新为ADC和PWM的驱动
 * Copyright (c) 2024 by Jsir2022, All Rights Reserved.
 * @verbatim
 * ==============================================================================
 *
 * ==============================================================================
 * @endverbatim
 */
#include "motor_drive.h"
#include "motor_ctrl.h"

#include "tim.h"
#include "adc.h"

static stMotorDrive_ADC_type MD_ADC;

//=================================用户修改======================================
// ARR设置函数
void MD_setARR(uint16_t _value)
{
    TIM1->ARR = _value;
}
// CCR设置函数
void MD_setCCR_A(uint16_t _value)
{
    TIM1->CCR1 = _value;
}
void MD_setCCR_B(uint16_t _value)
{
    TIM1->CCR2 = _value;
}
void MD_setCCR_C(uint16_t _value)
{
    TIM1->CCR3 = _value;
}
//===================================END========================================

/**
 * @brief   ADC注入转换完成回调函数
 * @note    电机实时控制进程在此，这与FOC算法息息相关
 * @param   {ADC_HandleTypeDef} *hadc
 * @return  {*}
 */
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == ADC1)
    {
        // 翻转IO看采样完成的时间点
        HAL_GPIO_TogglePin(INJECT_GPIO_Port, INJECT_Pin);
        MD_ADC.ia = ADC1->JDR1;
        MD_ADC.ib = ADC1->JDR2;
        MD_ADC.ic = ADC1->JDR3;
        MD_ADC.ibus = ADC1->JDR4;

        MC.focPara.i_a = (float)(MD_ADC.ia - MD_ADC.ia_offs) * I_Ratio;
        MC.focPara.i_b = (float)(MD_ADC.ib - MD_ADC.ib_offs) * I_Ratio;
        MC.focPara.i_c = (float)(MD_ADC.ic - MD_ADC.ic_offs) * I_Ratio;
        MC.focPara.i_bus = (float)(MD_ADC.ibus - MD_ADC.ibus_offs) * I_Ratio;

        Motor_Ctrl_runState();
    }
    else if (hadc->Instance == ADC2)
    {
        // 直接测量每相电压是测不出的，得用电流和电阻反推。
        MD_ADC.va = ADC2->JDR1;
        MD_ADC.vb = ADC2->JDR2;
        MD_ADC.vc = ADC2->JDR3;
        MD_ADC.vbus = ADC2->JDR4;

        MC.focPara.v_a = (float)(MD_ADC.va) * V_Ratio;
        MC.focPara.v_b = (float)(MD_ADC.vb) * V_Ratio;
        MC.focPara.v_c = (float)(MD_ADC.vc) * V_Ratio;
        MC.focPara.v_bus = (float)(MD_ADC.vbus) * V_Ratio;
    }
}

/**
 * @brief   获取电流采样运放的偏置
 * @note
 * @return  {*}
 */
void Motor_Drive_getADCOffs(void)
{
    float _SumA, _SumB, _SumC, _SumBus;

    for (int i = 0; i < 100; i++)
    {
        HAL_Delay(1);
        _SumA += (float)(MD_ADC.ia);
        _SumB += (float)(MD_ADC.ib);
        _SumC += (float)(MD_ADC.ic);
        _SumBus += (float)(MD_ADC.ibus);
    }

    MD_ADC.ia_offs = _SumA / 100.0f;
    MD_ADC.ib_offs = _SumB / 100.0f;
    MD_ADC.ic_offs = _SumC / 100.0f;
    MD_ADC.ibus_offs = _SumBus / 100.0f;
}

void Motor_Drive_startPWM(void)
{
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
}

void Motor_Drive_stopPWM(void)
{
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
}

/**
 * @brief   设置电机为滑行的PWM
 * @note    满占空比相当于自举失效了，全部管都不导通
 * @return  {*}
 */
void Motor_Drive_sildePWM(void)
{
    MD_setCCR_A(PWM_AAR_VAL);
    MD_setCCR_B(PWM_AAR_VAL);
    MD_setCCR_C(PWM_AAR_VAL);
}

/**
 * @brief   设置电机为急停的PWM
 * @note    下管全部打开，电机短路急停
 * @return  {*}
 */
void Motor_Drive_breakPWM(void)
{
    MD_setCCR_A(0);
    MD_setCCR_B(0);
    MD_setCCR_C(0);
}

/**
 * @brief   设置三相PWM的占空比
 * @note    三相占空比定义域[0,1]，而实际最大占空比是99%，再高就失去了控制的功能
 * @param   {float} _A A相占空比
 * @param   {float} _B B相占空比
 * @param   {float} _C C相占空比
 * @return  {*}
 */
void Motor_Drive_setPWM(float _A, float _B, float _C)
{
    // 三相占空比定义域[0,1]，而实际最大占空比是99%，再高就失去了控制的功能
    _A *= PWM_AAR_VAL;
    _B *= PWM_AAR_VAL;
    _C *= PWM_AAR_VAL;
    MD_setCCR_A((uint16_t)(_A > PWM_CRR_VAL ? PWM_CRR_VAL : _A));
    MD_setCCR_B((uint16_t)(_B > PWM_CRR_VAL ? PWM_CRR_VAL : _B));
    MD_setCCR_C((uint16_t)(_C > PWM_CRR_VAL ? PWM_CRR_VAL : _C));
}

/**
 * @brief   电机驱动所需的片上外设初始化
 * @note
 * @return  {*}
 */
void Motor_Drive_initHardware(void)
{
    // 设置TIM的ARR值
    MD_setARR(PWM_AAR_VAL);
    // 设置各路CCR初始值
    Motor_Drive_sildePWM();
    // 启动电机三相全桥PWM
    Motor_Drive_startPWM();
    // 启动Trigger触发的PWM
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, PWM_CRR_VAL);
    // 启动ADC注入捕获中断
    HAL_ADCEx_InjectedStart_IT(&hadc1);
    HAL_ADCEx_InjectedStart_IT(&hadc2);
    // 获取ADC电流采样偏置
    Motor_Drive_getADCOffs();
}